<?php
/**
 * Ecart
 * 
 * This file is part of Ecart.
 * 
 * Ecart is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Ecart is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with Ecart.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * @category    Ecart
 * @package     Ecart_View
 * @copyright   Copyright 2008-2009 E-Cart LLC
 * @license     GNU Public License V3.0
 */

/**
 * 
 * @category    Ecart
 * @package     Ecart_View
 * @author      Ecart Core Team <core@ecartcommerce.com>
 */
class Ecart_Layout extends Zend_Layout
{

    /**
     * @static
     * @var string
     */
    private static $_template;
    
    /**
     * Box to Block assignment
     *
     * @var array
     */
    protected $_assignments;
    
    protected $_tabAssignments;
    
    protected $_pages;
    
    protected $_layout = null;
    
    protected $_ecartLayout = null;

    protected $_defaultLayout = '3columns';
    
    /**
     * Static method for initialization with MVC support
     *
     * @static
     * @param  string|array|Zend_Config $options 
     * @return Ecart_Layout
     */
    public static function startMvc($options = null)
    {
        if (null === self::$_mvcInstance) {
            self::$_mvcInstance = new self($options, true);
        } else {
            self::$_mvcInstance->setOptions($options);
        }

        return self::$_mvcInstance;
    }

    /**
     * Return current template
     *
     * @static
     * @param string ['front' || 'admin']
     * @return array
     */
    public static function getTemplate($area = 'front')
    {
        if (null !== self::$_template) {
            return self::$_template;
        }
        if ($area == 'admin') {
            $templateId = Ecart::config()->design->main->adminTemplateId;
        } else {
            $templateId = Ecart::config()->design->main->frontTemplateId;
        }

        self::$_template = Ecart::model('core/template')
            ->select()
            ->where('id = ?', $templateId)
            ->fetchRow()
            ;
        self::$_template = Ecart::model('core/template')->fetchRow(
            Ecart::db()->quoteInto('id = ? ', $templateId)
        )->toArray();
        return self::$_template;
    }
    
    public function setAssignments($assignments)
    {
        $this->_assignments = $assignments;
    }
    
    /**
     * Compares requests
     * 
     * @param array $node
     * @param array $rewriteNode
     * @return bool
     */
    private function _catRewrite($node, $rewriteNode)
    {
        if ((0 > strcmp($node['module_name'], $rewriteNode['module_name'])) ||
            (0 > strcmp($node['controller_name'], $rewriteNode['controller_name'])) ||
            (0 > strcmp($node['action_name'], $rewriteNode['action_name'])))
        {
            return true;
        }
        return false;
    }
    
    public function getLayout()
    {
        if (Zend_Registry::get('area') == 'admin') {
            return 'layout';
        }
        
        if (null !== $this->_layout) {
            $this->_ecartLayout = 'layout' . substr($this->_layout, strpos($this->_layout, '_'));
        } elseif (null === $this->_ecartLayout) {
            $pages = $this->getMatchedPages();
            $templateId = Ecart::config()->design->main->frontTemplateId;
            
            $rows = Ecart::single('core/template_layout_page')
                ->select()
                ->where('template_id = ?', $templateId)
                ->where('page_id IN(?)', array_keys($pages))
                ->fetchAll()
                ;
                        
            $layout = '';
            $pageId = null;
            foreach ($rows as $row) {
                if (null !== $pageId && 
                    !$this->_catRewrite($pages[$pageId], $pages[$row['page_id']])) {
                    
                    continue;
                }
                $pageId = $row['page_id'];
                $layout = $row['layout'];
            }
            
            if (empty($layout)) {
                $layout = $this->_getDefaultLayout();
            }
            
            $this->_ecartLayout = 'layout' . substr($layout, strpos($layout, '_'));
        }

        return $this->_ecartLayout;
    }
    
    private function _getDefaultLayout()
    {
        $template = Ecart::single('core/template')
            ->find(Ecart::config()->design->main->frontTemplateId)
            ->current();
        if ($template instanceof Ecart_Db_Table_Row 
            || !empty($template->default_layout)) {
            
            return $template->default_layout;
        }
        return $this->_defaultLayout;
    }
    
    public function getMatchedPages()
    {
        if (null === $this->_pages) {
            $request = Zend_Controller_Front::getInstance()->getRequest();
            list($namespace, $module) = explode('_', $request->getModuleName(), 2);
            $this->_pages = Ecart::single('core/page')->getPagesByRequest(
                strtolower($module), 
                $request->getControllerName(),
                $request->getActionName() 
            );
        }
        return $this->_pages;
    }
    
    protected function _getAssignments($blockName = '')
    {
        if (null === $this->_assignments) {
            $pages = $this->getMatchedPages();
            $assignments = array();
            $tabAssignments = array();
            if (count($pages)) {
                $rows = Ecart::single('core/template_box')->getCustomInfo(
                    Ecart::config()->design->main->frontTemplateId, 
                    array_keys($pages)
                );
                foreach ($rows as $row) {
                    $block = !empty($row['other_block']) ? $row['other_block'] : $row['block'];

                    if (isset($assignments[$block][$row['id']])) {
                        $page_id = $assignments[$block][$row['id']]['page_id'];
                        if (!$this->_catRewrite($pages[$page_id], $pages[$row['page_id']])) {
                            continue;
                        }
                    }
                    
                    list($namespace, $module, $box) = explode('_', $row['class']); // example: Ecart_Locale_Currency
                    
                    if (!isset($module) || !isset($box)) {
                        continue;
                    }
                    
                    $assignments[$block][$row['id']] = array(
                        'boxCategory' => ucfirst($namespace),
                        'boxModule'   => ucfirst($module),
                        'boxName'     => ucfirst($box),
                        'template' => $row['template'],
                        'tabContainer' => $row['tab_container'],
                        'sort_order' => $row['sort_order'],
                        'page_id'  => $row['page_id'],
                        'show'     => $row['box_show']
                    );
                    if (!empty($row['config'])) {
                        $assignments[$block][$row['id']]['config'] = $row['config'];
                    }
                    
                    if (strstr($row['class'], 'Ecart_Cms_Block_')) {
                        $static_block = trim(str_replace('Ecart_Cms_Block_', '', $row['class']));
                        if (empty($static_block)) {
                            continue;
                        }
                        $assignments[$block][$row['id']]['staticBlock'] = $static_block;
                    }
                    if (null !== $row['tab_container']) {
                        $tabAssignments[$block][$row['id']] = $assignments[$block][$row['id']];
                    }
                }
            }
            $this->_assignments = &$assignments;
            $this->_tabAssignments = &$tabAssignments;
            Ecart_Core_Box_Abstract::setView($this->getView());
        }
        
        if (empty($blockName) || !array_key_exists($blockName, $this->_assignments)) {
            return array();
        }
        
        return $this->_assignments[$blockName];
    }
    
    public function __get($key)
    {
        if (Zend_Registry::get('area') == 'admin') {
            return parent::__get($key);
        }
        
        $beforeContent = $afterContent = '';
        Zend_Registry::set('rendered_boxes', array());
        foreach ($this->_getAssignments($key) as $boxId => $boxConfig) {
            
            if (in_array($boxId, Zend_Registry::get('rendered_boxes')) ||
                !$this->_isBoxEnabled($boxConfig))
            {
                continue;
            }
            $boxContent = $this->_getBoxContent($boxConfig);
            
            if (!empty($boxConfig['tabContainer'])) {
                foreach ($this->_tabAssignments[$key] as $tabBoxId => $tabBoxConfig) {
                    if ($tabBoxId == $boxId 
                        || $boxConfig['tabContainer'] != $tabBoxConfig['tabContainer']
                        || !$this->_isBoxEnabled($tabBoxConfig))
                    {
                        continue;
                    }
                    
                    $boxContent .= $this->_getBoxContent($tabBoxConfig);
                    
                    $rendered_boxes = Zend_Registry::get('rendered_boxes');
                    $rendered_boxes[] = $tabBoxId;
                    Zend_Registry::set('rendered_boxes', $rendered_boxes);
                }
                $this->_wrapContentIntoTabs($boxContent, $boxConfig['tabContainer']);
            }
            
            if ($boxConfig['sort_order'] < 0) {
                $beforeContent .= $boxContent;
            } else {
                $afterContent .= $boxContent;
            }
        }

        return $beforeContent . parent::__get($key) . $afterContent;
    }
    
    private function _getBoxContent($boxConfig)
    {
        $boxClass = $boxConfig['boxCategory'] . '_' . $boxConfig['boxModule'] . '_Box_' . $boxConfig['boxName'];
        if ($box = $this->getView()->box($boxClass, $boxConfig)) {
            $html = null;
            $obStartLevel = ob_get_level();
            try {
                $html = $box->toHtml();
            } catch (Exception $e) {
                while (ob_get_level() > $obStartLevel) {
                    $html .= ob_get_clean();
                }
                throw $e;
            }
            return $html;
        }
        return '';
    }
    
    private function _isBoxEnabled($boxConfig)
    {
        if (!$boxConfig['show']) {
            return false;
        }
        if (strpos($boxConfig['boxModule'], 'Payment') === 0 /*|| strpos($box['module'], 'Shipping') === 0*/) {
            $method = Ecart::single(
                $boxConfig['boxModule'] . '/' . str_replace('Button', '', $boxConfig['boxName'])
            );
            return $method->isEnabled();
        }
        return true;
    }
    
    private function _wrapContentIntoTabs(&$content, $class)
    {
        $content = "<div class='tab-container box tabs-{$class}'>{$content}</div>";
    }
}